package com.jse.tpl;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;

import com.jse.Fs;
import com.jse.Io;
import com.jse.Jse;
import com.jse.Lang;

/**
 * 设置 ISourceFactory 用于为 engine 切换不同的 ISource 实现类
 * ISource 用于从不同的来源加载模板内容
 *
 * <pre>
 * 配置为 ClassPathSourceFactory 时特别注意：
 *    由于 JFinal 会在 configEngine(Engine me) 方法调用 “之前”，会默认调用一次如下方法：
 *       me.setBaseTemplatePath(PathKit.getWebRootPath())
 *
 *    而 ClassPathSourceFactory 在以上默认值下不能工作，所以需要通过如下方式清掉该值：
 *       me.setBaseTemplatePath(null)
 *
 *    或者配置具体要用的 baseTemplatePath 值，例如：
 *       me.setBaseTemplatePath("view");
 * </pre>
 */
public class Source {

	private Path absfile;
	private StringBuilder content;
	private long lastModified;
	private boolean isStringSource;
	private boolean isClassPathSource;
	private Charset charset=StandardCharsets.UTF_8;
	private String fileName;
	private String encoding;
	private ClassLoader classLoader;
	private URL url;
	private boolean isInJar;
	
	public Source(String path, String fileName, String encoding) {
		this.fileName = fileName;
		this.encoding=encoding;
		if(path==null) {
			this.absfile=Path.of(fileName);
			this.lastModified = Fs.lastModified(absfile);
		}else if(path.equals("$")) {
			this.classLoader=Lang.loader();
			this.url = classLoader.getResource(fileName.charAt(0)=='/'?fileName.substring(1):fileName);
			if ("file".equalsIgnoreCase(url.getProtocol())) {
				isInJar = false;
				this.absfile=Path.of(Jse.classpath,fileName);
				this.lastModified = new File(url.getFile()).lastModified();
			} else {
				isInJar = true;
				lastModified = -1;
			}
		}else if(path.equals("js")||path.equals("jspath")) {
			this.absfile=Path.of(Jse.jspath(),fileName);
			this.lastModified = Fs.lastModified(absfile);
		}else if(path.equals("web")||path.equals("webapp")) {
			this.absfile=Path.of(Jse.webapp(),fileName);
			this.lastModified = Fs.lastModified(absfile);
		}else {
			this.absfile=Path.of(path,fileName);
			this.lastModified = Fs.lastModified(absfile);
		}
	}
	//字符串StringSource
	public Source(String content, boolean cache) {
		this(content, cache?Lang.md5(content) : null);
	}
	//字符串
	public Source(String content,String key) {
		this.isStringSource=true;
		this.content = new StringBuilder(content);
		this.fileName = key;
	}

	public String getFileName() {
		return fileName;
	}

	public boolean isModified() {
		if(isStringSource)return false;
		return isInJar ? false : lastModified != Fs.lastModified(absfile);
	}

	public String getCacheKey() {
		if(isStringSource)return fileName;
		return fileName;
	}

	public StringBuilder getContent() {
		if(!isStringSource) {
			if (isInJar) {		// 如果模板文件不在 jar 包文件之中，则需要更新 lastModified 值
				try {
					return new StringBuilder(Io.readString(url.openStream()));
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
			}else {
				this.lastModified = Fs.lastModified(absfile);
				return new StringBuilder(Fs.readString(absfile,charset));
			}
		}
		return content;
	}

	public String getEncoding() {
		return encoding;
	}
	public Path getAbsfile() {
		return absfile;
	}
	public long getLastModified() {
		return lastModified;
	}

	

}
